package com.didi.gulimall.ware.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.didi.gulimall.api.ProductApiService;
import com.didi.gulimall.common.constant.WareConstant;
import com.didi.gulimall.common.to.SkuHasStockVo;
import com.didi.gulimall.common.utils.PageUtils;
import com.didi.gulimall.common.utils.Query;
import com.didi.gulimall.common.utils.R;
import com.didi.gulimall.common.vo.OrderItemVo;
import com.didi.gulimall.ware.dao.WareSkuDao;
import com.didi.gulimall.ware.entity.WareInfoEntity;
import com.didi.gulimall.ware.entity.WareSkuEntity;
import com.didi.gulimall.ware.service.WareInfoService;
import com.didi.gulimall.ware.service.WareSkuService;
import com.didi.gulimall.ware.vo.WareSkuVO;
import com.didi.gulimall.ware.vo.WarehousingVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {
    @Autowired
    private WareInfoService wareInfoService;
    @Autowired
    private ProductApiService productApiService;


    /**
     * wareId: 123,//仓库id
     * skuId: 123//商品id
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("ware_id");
        String wareId = (String) params.get("wareId");
        if (StringUtils.isNotBlank(wareId)) {
            queryWrapper.eq("ware_id", wareId);
        }
        String skuId = (String) params.get("skuId");
        if (StringUtils.isNotBlank(skuId)) {
            queryWrapper.eq("sku_id", skuId);
        }

        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                queryWrapper
        );
        PageUtils pageUtils = new PageUtils(page);
        List<WareSkuEntity> records = page.getRecords();
        List<WareSkuVO> collect = records.stream().map(wareSkuEntity -> {
            WareSkuVO wareSkuVO = new WareSkuVO();
            BeanUtils.copyProperties(wareSkuEntity, wareSkuVO);
            WareInfoEntity byId = wareInfoService.getById(wareSkuEntity.getWareId());
            wareSkuVO.setWareName(byId.getName());
            return wareSkuVO;
        }).collect(Collectors.toList());
//
        pageUtils.setList(collect);
        return pageUtils;
    }

    @Override
    public void addStock(List<WarehousingVO> warehousings) {
        List<WareSkuEntity> collect = warehousings.stream().map(warehousing -> {
            QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper
                    .eq("sku_id", warehousing.getSkuId())
                    .eq("ware_id", warehousing.getWareId());
            WareSkuEntity wareSkuEntity = this.getOne(queryWrapper);
            if (wareSkuEntity == null) {
                wareSkuEntity = new WareSkuEntity();
                wareSkuEntity.setSkuId(warehousing.getSkuId());
                wareSkuEntity.setWareId(warehousing.getWareId());
                wareSkuEntity.setStockLocked(0);
                // TODO 循环调用接口 需要优化
                R info = productApiService.info(warehousing.getSkuId());
                Map<String, Object> data = (Map<String, Object>) info.get("skuInfo");
                if (info.getCode() == 0) {
                    wareSkuEntity.setSkuName((String) data.get("skuName"));
                }
                wareSkuEntity.setStock(warehousing.getSkuNum());
            } else {
                wareSkuEntity.setStock(wareSkuEntity.getStock() + warehousing.getSkuNum());
            }
            return wareSkuEntity;
        }).collect(Collectors.toList());
        this.saveBatch(collect);
    }

    @Override
    public void saveWareSku(WareSkuEntity wareSku) {
        QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("sku_id", wareSku.getSkuId())
                .eq("ware_id", wareSku.getWareId());
        WareSkuEntity one = this.getOne(queryWrapper);
        if (one == null) {
            R info = productApiService.info(wareSku.getSkuId());
            Map<String, Object> data = (Map<String, Object>) info.get("skuInfo");
            if (info.getCode() == 0) {
                wareSku.setSkuName((String) data.get("skuName"));
            }
            this.save(wareSku);
        } else {
            one.setStock(wareSku.getStock() + one.getStock());
            this.updateById(one);
        }

    }

    @Override
    public void updateWareSku(WareSkuEntity wareSku) {

        this.updateById(wareSku);
    }

    @Override
    public List<SkuHasStockVo> getSkusHasStock(List<Long> skuIds) {
        QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("sku_id", skuIds);
        List<WareSkuEntity> wareSkuEntities = this.baseMapper.selectList(queryWrapper);
        return wareSkuEntities.stream().map(wareSku -> {
            SkuHasStockVo skuHasStockVo = new SkuHasStockVo();
            skuHasStockVo.setSkuId(wareSku.getSkuId());
            skuHasStockVo.setHasStock(wareSku.getStock() - wareSku.getStockLocked() > 0);
            return skuHasStockVo;
        }).collect(Collectors.toList());
    }

    @Override
    public Map<Long, Boolean> getSkusHasStockbByCartItem(List<OrderItemVo> orderItemVos) {
        Map<Long, Boolean> map = new HashMap<>();
        for (OrderItemVo orderItemVo : orderItemVos) {
            QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("sku_id", orderItemVo.getSkuId());
            List<WareSkuEntity> wareSkuEntities = baseMapper.selectList(queryWrapper);
            if (CollectionUtils.isNotEmpty(wareSkuEntities)) {
                for (WareSkuEntity wareSkuEntity : wareSkuEntities) {
                    if (wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() >= orderItemVo.getCount()) {
                        map.put(orderItemVo.getSkuId(), true);
                        break;
                    } else {
                        map.put(orderItemVo.getSkuId(), false);
                    }
                }
            } else {
                map.put(orderItemVo.getSkuId(), false);
            }
        }
        return map;
    }

    @Override
    public List<Long> listWareIdHasSkuStock(Long skuId, Integer count) {
        return baseMapper.listWareIdHasSkuStock(skuId, count);
    }

    @Override
    public Long lockSkuStock(Integer num, Long skuId, Long wareId) {

        return baseMapper.lockSkuStock(num, skuId, wareId);
    }

    @Override
    public void unLook(Long skuId, Long wareId, Integer num, Integer hasStock) {
        if (hasStock.equals(WareConstant.LOCK_INVENTORY)) {
            baseMapper.unLookStock(skuId, wareId, num);
        }else if (hasStock.equals(WareConstant.DEDUCTED_INVENTORY)){
            baseMapper.releaseInventory(skuId, wareId, num);
        }


    }

    @Override
    public void deductionInventory(Long skuId, Long wareId, Integer skuNum) {
        baseMapper.deductionInventory(skuId, wareId, skuNum);
    }

}